#ifndef IO_COM_H
#define IO_COM_H

#include <QSerialPort>
#include <QSerialPortInfo>
#include <QThread>
#include <string>
#include <QMutex>
#include <map>
#include <vector>

#define io_COM_waitForReadyRead_ms 10
#define io_COM_ENABLE_HARD_RST_via_DTR_pin
using IOCollection = std::map<std::string, std::string>; // < ComName, ComInfo >

typedef enum{
    reserve,
    closed,
    opening,
    ready,
    txing,
    error,
    procing
} com_sta;

class io_COM : public QThread{
    Q_OBJECT
public:
    io_COM();
    ~io_COM();
    void run();
    const IOCollection& GetIOCollection() const { return m_IOCollection; }
    void RefreshComInfo();
    std::vector<uint8_t> RecvPortData();
    com_sta GetSta() { return sta; }
    bool tReady() { return (sta==ready) && (COM->isOpen()); }
    void clear();
    typedef struct{
        int64_t bufsize;
        int proced;
        int err;
        int speed;
        int mdelay;
        double ratio;
        void clear();
        QString getInfo();
    } ioINFO;
    ioINFO rxINFO, txINFO;
signals:
    void ioCOMRxBytes(QByteArray rx);
    void io_COM_txDone();
public slots:
    void io_COM_echo_open(QString portname);
    void io_COM_echo_close();
    void io_COM_echo_send();
    void io_COM_echo_tx(QByteArray src);
    void io_COM_echo_txDoneDelay(int ms);
    void io_COM_echo_rxDoneDelay(int ms);
    void io_COM_echo_procDone(int proced_cnt);
    void io_COM_echo_error(QSerialPort::SerialPortError info);
    void io_COM_echo_hardRST(bool tHigh);
private:
    com_sta sta;
    bool tEnableLOG;
    bool sig_BtSendFlag;
    bool sig_DataReadyFlag;
    bool sig_openCOMflag;
    bool sig_closeCOMflag;
    bool sig_txFlag;
    QString sig_openCOMname;
    QByteArray rx_buffer;
    QByteArray tx_buffer_pool;
    int rmove_rx_cnt;
    bool proced_flag;
    IOCollection m_IOCollection;
    QList<QSerialPortInfo> m_comInfoHistory;
    QSerialPortInfo COM_Info;
    QSerialPort* COM;
    bool COM_open(QString portname);
    void COM_close();
    void io_COM_tx(QByteArray src);
    void thread_rst();
    void thread_fatal(QString str);
    int io_preProcPack(QByteArray src);
    bool tComErr = false;

    QString sta2str(com_sta sta);

};

#endif // IO_COM_H
